package tech.heptagram.staff.cas.service.staff.impl;


import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import tech.heptagram.staff.cas.common.ArgumentException;
import tech.heptagram.staff.cas.common.AssertUtils;
import tech.heptagram.staff.cas.domain.info.RolePermissionReq;
import tech.heptagram.staff.cas.domain.po.Role;
import tech.heptagram.staff.cas.domain.po.RoleDataAuth;
import tech.heptagram.staff.cas.domain.po.RoleMenu;
import tech.heptagram.staff.cas.mapper.CasMenuMapper;
import tech.heptagram.staff.cas.mapper.CasRoleDataAuthMapper;
import tech.heptagram.staff.cas.mapper.CasRoleMapper;
import tech.heptagram.staff.cas.mapper.CasRoleMenuMapper;
import tech.heptagram.staff.cas.mapper.CasRoleStaffMapper;
import tech.heptagram.staff.cas.service.staff.CasRoleService;

/**
 * 角色ServiceImpl
 *
 * @author zilaiye
 * @date 2017/12/8
 */
@Service
public class CasRoleServiceImpl implements CasRoleService {

    private static final int ADMIN_ID = 1;

    @Resource
    private CasRoleMapper casRoleMapper;

    @Resource
    private CasRoleMenuMapper casRoleMenuMapper;

    @Resource
    private CasRoleStaffMapper casRoleStaffMapper;

    @Resource
    private CasMenuMapper casMenuMapper;

    @Resource
    private CasRoleDataAuthMapper casRoleDataAuthMapper;

    /**
     * 获取所有角色列表
     *
     * @return all roles list
     */
    @Override
    public List<Role> findAll() {
        List<Role> lstRoleVos = casRoleMapper.selectAll();
        return lstRoleVos;
    }

    /**
     * 获取指定ID的角色信息
     *
     * @param roleId roleId
     * @return role info
     */
    @Override
    public Role findById(Integer roleId) {
        if (Objects.isNull(roleId)) {
            return null;
        }
        Role role = casRoleMapper.selectById(roleId);
        return role;
    }

    /**
     * 获取员工的角色IDs
     *
     * @param staffCode
     * @return
     */
    @Override
    public List<Integer> findRoleIdsByStaffCode(String staffCode) {
        List<Role> roles = findRolesByStaffCode(staffCode);
        List<Integer> roleIds = roles.stream().map(Role::getId).collect(Collectors.toList());
        return roleIds;
    }

    @Override
    public List<Role> findRolesByStaffCode(String staffCode) {
        if (StringUtils.isEmpty(staffCode)) {
            return new ArrayList<>();
        }
        List<Role> roles = casRoleMapper.selectByStaffCode(staffCode);
        return roles;
    }

    @Override
    public List<Role> findRolesByMenuId(Integer menuId) {
        if(Objects.isNull(menuId)){
            return new ArrayList<>();
        }

        List<Role> roles = casRoleMapper.selectByMenuId(menuId);
        return roles;
    }

    /**
     * 保存角色
     *
     * @param role
     * @return
     */
    @Override
    public Integer saveRole(Role role) {
        AssertUtils.notNull(role, "角色不能为Null");
        AssertUtils.notNull(role.getCreatedBy(), "创建人不能为空");
        AssertUtils.notNull(role.getModifiedBy(), "最后更新人不能为空");
        AssertUtils.notNull(role.getName(), "角色名不能为空");

        Role role1 = casRoleMapper.selectByName(role.getName());
        if (Objects.nonNull(role1)) {
            throw new ArgumentException("已经有相同名称的角色了");
        }
        casRoleMapper.insert(role);
        return role.getId();
    }

    /**
     * 更新角色
     *
     * @param role
     */
    @Override
    public void updateRole(Role role) {
        AssertUtils.notNull(role, "角色不能为Null");
        AssertUtils.greaterThanZero(role.getId(), "要更改的角色ID必须大于0");
        AssertUtils.notNull(role.getModifiedBy(), "修改人不能为空");
        AssertUtils.notNull(role.getName(), "角色名不能为空");

        Role role1 = casRoleMapper.selectByName(role.getName());
        if (Objects.nonNull(role1) && role.getId().intValue() != role1.getId().intValue()) {
            throw new ArgumentException("已经有相同名称的角色了");
        }

        casRoleMapper.update(role);
    }

    /**
     * 删除一个角色
     *
     * @param roleId id
     */
    @Override
    @Transactional
    public void deleteById(Integer roleId, String deleteBy) {
        AssertUtils.notNull(deleteBy, "删除人不能为空");
        AssertUtils.notNull(roleId, "角色编号不能为空");

        if (roleId.intValue() == ADMIN_ID) {
            throw new ArgumentException("超级管理员角色不能被删除");
        }

        // 删除角色菜单关系
        casRoleMenuMapper.deleteByRoleId(roleId, deleteBy);

        // 删除角色员工关系
        casRoleStaffMapper.deleteByRoleId(roleId, deleteBy);

        // 删除角色
        casRoleMapper.deleteById(roleId, deleteBy);
    }

    @Override
    @Transactional
    public Integer saveRolePermission(RolePermissionReq req) {
        AssertUtils.notNull(req.getCreatedBy(),"创建人不能为空");
        AssertUtils.notNull(req.getRoleId(),"角色编号不能为空");

        // 先清空
        casRoleMenuMapper.deleteByRoleId(req.getRoleId(), req.getCreatedBy());

        // 这外逻辑有点复杂了, 由于前台传过来的页面可能不包括父菜单, 所以过滤一下所有菜单的父级菜单, 有子菜单权限, 则必有父菜单权限。
//        List<Menu> allMenus = casMenuMapper.selectByIds(req.getMenuIds());
//        for (Menu menu : allMenus) {
//            String[] parentIds = StringUtils.split(menu.getParentIdStrand(), ";");
//            if (ArrayUtils.isNotEmpty(parentIds)) {
//                for (String parentId : parentIds) {
//                    if (StringUtils.isNotEmpty(parentId) && !parentId.equals("0")) {
//                        boolean containsParentId = req.getMenuIds().contains(Integer.valueOf(parentId));
//                        if (!containsParentId) {
//                            req.getMenuIds().add(Integer.valueOf(parentId));
//                        }
//                    }
//                }
//            }
//        }

        // 再插入
        for (Integer menuId : req.getMenuIds()) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(req.getRoleId());
            roleMenu.setMenuId(menuId);
            roleMenu.setCreatedBy(req.getCreatedBy());
            roleMenu.setModifiedBy(req.getCreatedBy());
            casRoleMenuMapper.insert(roleMenu);
        }

        return req.getMenuIds().size();
    }

    @Override
    public Integer saveRoleDataAuth(RolePermissionReq req) {
        AssertUtils.notNull(req.getCreatedBy(),"创建人不能为空");
        AssertUtils.notNull(req.getRoleId(),"角色编号不能为空");

        // 先清空
        casRoleDataAuthMapper.deleteByRoleId(req.getRoleId(), req.getCreatedBy());

        // 再插入
        RoleDataAuth roleDataAuth = new RoleDataAuth();
        roleDataAuth.setRoleId(req.getRoleId());
        roleDataAuth.setDataAuthId(req.getDataAuthId());
        roleDataAuth.setCreatedBy(req.getCreatedBy());
        roleDataAuth.setModifiedBy(req.getCreatedBy());

        casRoleDataAuthMapper.insert(roleDataAuth);
        return 0;
    }

}
